# -*- mode: python -*-
###
#
# (c) 2000-2007 Wijnand Modderman <wijnand at tehmaze dot com>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#   * Redistributions of source code must retain the above copyright notice,
#     this list of conditions, and the following disclaimer.
#   * Redistributions in binary form must reproduce the above copyright notice,
#     this list of conditions, and the following disclaimer in the
#     documentation and/or other materials provided with the distribution.
#   * Neither the name of the author of this software nor the name of
#     contributors to this software may be used to endorse or promote products
#     derived from this software without specific prior written consent.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
###

__revision__ = '$Hg:$'

# system imports

# DDB imports
from ddb.log import log
from ddb.tools import syntax
from ddb.user import userRegister, makeMask
from ddb.settings import USER_FLAG
from ddb.access import access

# system imports
import sets

# DDB exports
EXPORT=['Usermod']

class Usermod:
    def __init__(self):
        self.callbacks = {}

    @access('nu', 'nu')
    def hostadd(self, event):
        """<username> <hostmask>

        add <hostmask> to <username>."""
        if not event.args or len(event.args.split()) != 2:
            event.reply(syntax())
            return
        event.args = event.args.split()
        if not userRegister.get(event.args[0]):
            event.reply('no such user')
            return
        if not '@' in event.args[1]:
            event.args[1] = makeMask('*@%s' % event.args[1])
        if '!' in event.args[1]:
            event.args[1] = makeMask(event.args[1].split('!')[1])
        hosts = userRegister.config.get(event.args[0], 'mask')
        if not hosts:
            hosts = []
        found = False
        for i in range(0, len(hosts)):
             if hosts[i].lower() == event.args[1].lower():
                found = True
        if not found:
            hosts.append(event.args[1])
        userRegister.config.set(event.args[0], 'mask', hosts)
        userRegister.save()
        event.reply('hostmask %s added' % event.args[1])

    def flag(self, event):
        """<flag>

        shows information about <flag>.
        """
        if not event.args:
            event.reply(syntax())
            return
        if not USER_FLAG.has_key(event.args.lower()):
            event.reply('flag not found')
        else:
            event.reply('flag \002%s\002: %s' % (event.args, USER_FLAG[event.args.lower()]))

    @access('nu', 'nu')
    def flags(self, event):
        """[<username>]

        if <username> is given, it lists flag for that user, otherwise, it
        will list the current user's flags."""
        if not event.args:
            event.reply(syntax())
            return
        if not userRegister.get(event.args):
            event.reply('user not found')
            return
        flags = userRegister.config.get(event.args, 'flag')
        print flags
        if flags:
            # blah, this should be simpler :-)
            flags.sort()
            flags = [tuple(x.split(',')) for x in flags]
            flags = [[x[0], [y for y in x[1]]] for x in flags]
            [x[1].sort() for x in flags]
            flags = ['on \002%s\002: %s' % (x[0], ','.join(x[1])) for x in flags]
            flags = ', '.join(flags)
        event.reply('user %s flags: %s' % (event.args, flags))

    @access('nu', 'nu')
    def flagadd(self, event):
        """<username> <*|channel> <flag>

        add <flag> to <username> on either <channel> or globally.
        """
        if not event.args or len(event.args.split()) != 3:
            event.reply(syntax())
            return
        event.args  = event.args.split()
        if not userRegister.get(event.args[0]):
            event.reply('no such user')
            return
        flags = userRegister.config.get(event.args[0], 'flag')
        if not flags:
            flags = []
        found = False
        for i in range(0, len(flags)):
            channel, flaglist = flags[i].split(',',1)
            if channel.lower() == event.args[1].lower():
                newflags = ''.join(sets.Set(list(flaglist + event.args[2])))
                flags[i] = '%s,%s' % (channel, newflags)
                found    = True
        if not found:
            newflags = ''.join(sets.Set(list(event.args[2])))
            flags.append('%s,%s' % (event.args[1], newflags))
        userRegister.config.set(event.args[0], 'flag', flags)
        userRegister.save()
        event.reply('flag added')

    @access('nu', 'nu')
    def flagdel(self, event):
        """<username> <*|channel> <flag>

        remove <flag> from <username> on either <channel> or globally.
        """
        if not event.args or len(event.args.split()) != 3:
            event.reply(syntax())

    @access('nu', 'nu')
    def useradd(self, event):
        """<nick> [<username>]

        adds <nick> to the user database, optionally specify a <username> to
        let the user be known with."""
        if not event.args or len(event.args.split(' ')) > 2:
            event.reply(syntax())
            return
        addNick = event.args
        addUser = event.args
        if ' ' in event.args:
            addNick, addUser = event.args.split(' ', 1)
        if userRegister.get(addUser):
            event.reply('there already is a user with that name')
            return
        self.callbacks[addNick.lower()] = [self._useradd, addUser, event.target, event.nick]
        event.raw('WHOIS %s %s' % (addNick, addNick))

    def _useradd(self, event):
        """called from this __hook__ if WHO reply received."""
        addNick = event.nick
        addUser, event.target, event.nick = self.callbacks[addNick.lower()][1:]
        del self.callbacks[addNick.lower()]
        newMask = makeMask(event.mask).split('!', 1)[1]
        if event.user:
            event.reply('not adding user %s (%s), already known as "%s"' % \
                (addUser, addNick, event.user))
        else:
            event.reply('adding user %s (%s), with mask: %s' % (addUser, 
                addNick, newMask))
            userRegister.add(addUser, newMask)

    @access('nou', 'nou')
    def usermerge(self, event):
        """<username> <nick>

        merges the hostmask of <nick> to <username>."""
        if not event.args or len(event.args.split()) != 2:
            event.reply(syntax())
            return
        mergeUser, mergeNick = event.args.split()
        if not userRegister.get(mergeUser.lower()):
            event.reply('user "%s" unknown, did you mean useradd?')
            return
        self.callbacks[mergeNick.lower()] = [self._usermerge, mergeUser, event.target, event.nick]
        event.raw('WHOIS %s %s' % (mergeNick, mergeNick))

    def _usermerge(self, event):
        """called from this __hook__ if WHOIS reply received."""
        mergeNick = event.nick
        mergeUser, event.target, event.nick = self.callbacks[mergeNick.lower()][1:]
        del self.callbacks[mergeNick.lower()]
        newMask = makeMask(event.mask).split('!', 1)[1]
        testUser = userRegister.match(newMask)
        if testUser:
            event.reply('there is already a user known with mask %s: %s' % (newMask, testUser))
            return
        if event.user:
            hosts = userRegister.config.get(mergeUser, 'mask')
            if not hosts:
                hosts = []
            found = False
            for i in range(0, len(hosts)):
                if hosts[i].lower() == event.args[1].lower():
                    found = True
            if not found:
                hosts.append(event.args[1])
                userRegister.config.set(mergeUser, 'mask', hosts)
                userRegister.save()
                event.reply('hostmask %s added to user %s' % (mergeUser, mergeNick))

    @access('n', 'n')
    def userdel(self, event):
        """<username>

        removes <username> from the user database."""
        if not event.args:
            event.reply(syntax())
            return
        delUser = event.args
        if not userRegister.get(delUser):
            event.reply('user not found')
            return
        if not 'n' in userRegister.rights(event.user, event.target) and \
            'n' in userRegister.rights(delUser, event.target):
            event.reply('can not remove an owner unless you are an owner')
            return
        userRegister.remove(delUser)
        event.reply('user "%s" removed' % delUser)

    @access('o', 'o')
    def user(self, event):
        """<username>

        show details about <username>."""
        if not event.args:
            event.reply(syntax())
            return
        if not userRegister.get(event.args):
            event.reply('no such user')
            return
        masks = userRegister.config.get(event.args, 'mask')
        if masks:
            masks.sort()
            masks = ', '.join(masks)
        flags = userRegister.config.get(event.args, 'flag')
        if flags:
            flags.sort()
            flags = ' '.join(flags)
        event.reply('user %s, flags: %s, masks: %s' % (event.args, flags, masks))

# vim:ts=4:sw=4:et:
